<script setup>
import {Chart} from "@antv/g2";
import {ref, onMounted, nextTick} from 'vue';
import {Graph} from "@antv/g6";
import {Link, Search} from '@element-plus/icons-vue'
import {useGridStore} from "../store/gridData";
import req from "../tools/request";
import RiskSectionDetial from "./RiskSectionDetial.vue";

let chart = null
let graph = null

const showData = ref(null)
const leftWith = ref(14)
const rightWith = ref(10)

const gutter = ref(20)
const zoom = ref(1.0)

const contextMenuVisible = ref(false)
const menuPosition = ref({x: 0, y: 0})
const menuTargetItem = ref()

const query = ref('')

const showLineInfo = ref(false)
const dialogRiskDetailVisible = ref(false)

function transformQueryList(data) {
  const list = [];
  const valueSet = new Set(); // 用于存储已经存在的 value 值

  data.forEach(item => {
    const value = item.line_name;
    if (!valueSet.has(value)) { // 检查 value 是否已经存在
      valueSet.add(value); // 将 value 添加到集合中
      list.push({value: value, label: item.cable_section_number}); // 添加到 list 中
    }
  });

  return list;
}

const queryList = ref(null);

const createFilter = (queryString) => {
  return (restaurant) => restaurant.value.toLowerCase().includes(queryString.toLowerCase());
};

const querySearchAsync = (queryString, cb) => {
  const results = queryString
      ? queryList.value.filter(createFilter(queryString)) : queryList.value
  cb(results)
}

const handleSearch = () => {
  if (query.value === '') return
  const result = useGridStore().state.cableSegmentData.filter(item => `${item.line_name}` === query.value)
  console.log(result)
  if (result === null) return
  let id_list = result.map(item => item.cable_section_number)
  console.log(id_list)
  console.log(query.value)
  graph.focusElement(id_list).then(() => {
    for (let id of id_list) {
      graph.setElementState(id, 'selected')
    }
    showData.value = useGridStore().state.data[query.value]
    nextTick(() => {
      showChart(showData.value)
      showLineInfo.value = true;
    })
  })
}

function transformData(data) {
  const nodes = [];
  const edges = [];

  data.forEach(item => {
    // 添加节点
    if (!nodes.some(node => node.id === item.start)) {
      nodes.push({
        id: `${item.start}`, label: `${item.start}`
      });
    }
    if (!nodes.some(node => node.id === item.end)) {
      nodes.push({
        id: `${item.end}`, label: `${item.end}`
      });
    }

    // 添加边
    edges.push({
      id: item.cable_section_number + "",
      source: `${item.start}`,
      target: `${item.end}`,
      label: `${item.line_name}`
    });
  });

  console.log({nodes, edges})
  return {nodes, edges};
}

function clickNode(evt) {
  const {targetType, target} = evt;
  if (targetType === 'node') {
    console.log('点击了节点:', target.id);
  } else if (targetType === 'edge') {

    const foundItem = useGridStore().state.cableSegmentGridData.find(item => `${item.cable_section_number}` === target.id);
    console.log(showData.value[0].line_name)
    console.log(foundItem.line_name)

    if (!showLineInfo.value || foundItem && foundItem.line_name !== showData.value[0].line_name) {
      showData.value = useGridStore().state.data[foundItem.line_name]

      let id_list = showData.value.map(item => item.cable_section_number)
      for (let id of id_list) {
        graph.setElementState(id, 'selected')
      }
      nextTick(() => {
        showChart(showData.value)
      })
    }

    showLineInfo.value = true;

  } else {
    if (!showLineInfo.value) return
    showLineInfo.value = false;
    showData.value = useGridStore().state.cableSegmentData.sort((a, b) => b.risk_score - a.risk_score)
    nextTick(() => {
      showChart(showData.value)
    })
  }
}

function rowClick(r) {
  graph.setElementState(r.cable_section_number, 'selected')
}

function rowDBClick(r) {
  viewSectionInfo(r.line_name)
}

function rowRClick(row, column, event) {
  event.preventDefault(); // 阻止默认右键菜单
  contextMenuVisible.value = true;
  console.log(row)
  menuTargetItem.value = useGridStore().state.cableSegmentData.find(item => item.cable_section_number === row.cable_section_number);
  menuPosition.value.x = event.clientX;
  menuPosition.value.y = event.clientY;
  console.log(menuTargetItem.value);
}

function menuClick(v) {
  contextMenuVisible.value = false
  if (v === 1) {
    console.log(menuTargetItem.value)
    viewSectionInfo(menuTargetItem.value.line_name)
  } else {
    dialogRiskDetailVisible.value = true
  }
}

const viewSectionInfo = (line_name) => {
  window.open('/dashboard?page=RelationMap&line_name=' + line_name, '_blank');
}

const getTagTypeByRiskLevel = (riskLevel) => {
  switch (riskLevel) {
    case '高风险':
      return 'danger';
    case '中风险':
      return 'warning';
    case '低风险':
      return 'success';
    default:
      return 'primary';
  }
}

const showChart = (val) => {
  console.log(val)
  const _data = [
    {id: '高风险', value: 0},
    {id: '中风险', value: 0},
    {id: '低风险', value: 0}
  ]
  let colors = []

  val.forEach(item => {
    if (item.risk_level === '高风险') {
      _data[0].value++
    } else if (item.risk_level === '中风险') {
      _data[1].value++
    } else {
      _data[2].value++
    }
  })

  console.log(_data)

  const data = _data.filter(item => item.value !== 0)
  data.forEach(item => {
    if (item.id === '高风险') colors.push("#ff001a")
    if (item.id === '中风险') colors.push("#ffcc00")
    if (item.id === '低风险') colors.push("#00ff22")
  })

  if (chart) {
    chart.clear()
  }

  chart = new Chart({container: "chart-container"});
  chart.options({
    type: "view",
    autoFit: true,
    coordinate: {type: "theta", innerRadius: 0.25, outerRadius: 0.8},
    scale: {
      color: {range: colors},
    },

    children: [
      {
        type: "interval",
        data: data.filter(item => item.value !== 0),
        encode: {y: "value", color: "id"},
        transform: [{type: "stackY"}],
        style: {radius: 4, stroke: "#fff", lineWidth: 2},
        animate: {enter: {type: "waveIn"}},
        legend: false,
        tooltip: false,
        labels: [
          {
            text: "value", fontWeight: "bold",
            fill: "#1e0808",
            fontSize: 15
          },
          {
            text: "id",
            position: "spider",
            connectorDistance: 0,
            fontWeight: "bold",
            textBaseline: "bottom",
            textAlign: "center",
            dy: -4,
          },
        ],
      },
      {
        type: "text",
        style: {
          text: "警告总数",
          x: "50%",
          y: 128,
          fontSize: 13,
          fontWeight: "bold",
          textAlign: "center",
        },
        tooltip: false
      },
      {
        type: "text",
        style: {
          text: `${val.length}`,
          x: "50%",
          y: 147,
          fontSize: 13,
          fontWeight: "bold",
          textAlign: "center",
        },
        tooltip: false
      },
    ],
  });

  chart.render();
}

onMounted(() => {
  req.get('/cable_segment_grid_data').then(res => {
    useGridStore().setCableSegmentGridData(res.data.data)
  }).then(() => {
    req.get('/cable_segment_data').then(res => {
      useGridStore().setCableSegmentData(res.data.data.cable_section_data)
      queryList.value = transformQueryList(useGridStore().state.cableSegmentGridData)
      let mapContainer = document.getElementById('map-container')
      graph = new Graph({
        container: mapContainer,
        width: mapContainer.clientWidth,
        height: mapContainer.clientHeight,
        data: transformData(useGridStore().state.cableSegmentGridData),
        animation: false,
        layout: {
          type: 'd3-force',
          link: {
            distance: 110,
            strength: 3
          },
          collide: {
            radius: 80,
          },
        },
        behaviors: ['drag-element',
          'drag-canvas',
          'zoom-canvas',
          'hover-activate', {
            type: 'click-select',
            degree: 1,
            multiple: true,
            trigger: ['shift'],
            onClick: clickNode
          }, {
            key: 'auto-adapt-label',
            type: 'auto-adapt-label',
            padding: 0,
            throttle: 200
          }],
        node: {
          style: {
            labelText: (d) => d.label,
            labelPlacement: 'middle',
            labelFill: 'rgba(0,0,0,0.82)',
          },
        },
        edge: {
          state: {
            selected: {
              stroke: '#00914D',
              lineWidth: 3,
            }
          },
          style: {
            stroke: (d) => {
              if (d.data.routineTest === '严重缺陷') return 'rgba(248,62,62,0.77)';
              if (d.data.routineTest === '一般缺陷') return 'rgba(66,180,246,0.79)';
              return '#000000';
            }, // 边颜色
            // stroke: '#f10000',
            lineWidth: 2, // 边的宽度
            label: true, // 开启边标签展示
            labelText: (d) => d.label, // 边标签文字
            labelPlacement: 'center', // 边标签相对于边的位置
            labelFill: '#000000', // 边标签文字颜色
            labelOffsetY: 15, // 边标签在y轴方向上的偏移量
          },
        },
        plugins: [
          {
            type: 'contextmenu',
            trigger: 'contextmenu', // 'click' or 'contextmenu'
            onClick: (v, target, current) => {
              let data = useGridStore().state.cableSegmentData.find(item => `${item.cable_section_number}` === current.id)
              if (v === "detail") {
                // viewSectionInfo(useGridStore().state.data[data.line_name])
                viewSectionInfo(data.line_name)
              }
            },
            getItems: () => {
              return [
                {name: '查看电缆段分布', value: 'detail'},
              ];
            },
            enable: (e) => e.targetType === 'edge',
          },
          {
            type: 'toolbar',
            getItems: () => [
              {id: 'zoom-in', value: 'zoom-in'},
              {id: 'zoom-out', value: 'zoom-out'},
              {id: 'auto-fit', value: 'auto-fit'},
            ],
            onClick: (value) => {
              // 处理按钮点击事件
              if (value === 'zoom-in') {
                zoom.value += 0.1
                zoom.value = Math.min(zoom.value, 3)
                graph.zoomTo(zoom.value);
              } else if (value === 'zoom-out') {
                zoom.value -= 0.1
                zoom.value = Math.max(zoom.value, 0.1)
                graph.zoomTo(zoom.value);
              } else if (value === 'auto-fit') {
                graph.fitView();
              }
            },
          },
          // {
          //   type: 'tooltip',
          //   trigger: 'hover',
          //   enable: (e) => e.targetType === 'node',
          //   getContent: (e, items) => {
          //     let result = '';
          //     items.forEach((item) => {
          //       result += `<p>地点名：${item.label}</p>`;
          //     });
          //     return result;
          //   },
          // },
        ],
      });
      graph.render().then(() => {
        showData.value = useGridStore().state.cableSegmentData.sort((a, b) => b.risk_score - a.risk_score)
        showChart(showData.value)
      })
    })
  }).then(() => {
    req.get('/data').then(res => {
      useGridStore().setData(res.data)
    })
  })
})

</script>

<template>
  <div>

    <el-row :gutter="gutter">
      <el-col :span="leftWith">
        <div class="search-filter-container no-select">
          <div class="search-filter-area">
            <el-autocomplete
                v-model="query"
                :fetch-suggestions="querySearchAsync"
                placeholder="电缆线路搜索"
                @select="handleSearch"
                clearable
            />
            <el-button :icon="Search" @click="handleSearch" circle/>
          </div>
        </div>
        <div id="map-container" class="grid-content"></div>
      </el-col>
      <el-col :span="rightWith">
        <div class="info">

          <div class="grid-content">
            <div v-if="showLineInfo">
              <h2 style="padding: 0 20px;display: grid;grid-template-columns: 5fr 1fr;">
                {{ showData[0].line_name }}
                <el-button style="justify-self: end;" :icon="Link" round
                           @click="viewSectionInfo(showData[0].line_name)">
                  查看电缆段分布
                </el-button>
              </h2>
            </div>
            <div v-else>
              <h2 style="padding: 0 20px;" class="no-select">
                所有线路信息
              </h2>
            </div>
            <div id="chart-container" style="width: 300px;height: 300px;"></div>
          </div>

          <el-popover
              v-model:visible="contextMenuVisible"
              placement="bottom-start"
              :popper-style="{left: `${menuPosition.x}px`,top: `${menuPosition.y}px`,position: 'absolute', padding: '5px 10px 2px 10px' }"
              trigger="contextmenu"
          >
            <div>
              <div v-if="menuTargetItem" class="menu-header-name">
                <strong>{{ menuTargetItem.line_name }}</strong>
              </div>
              <el-divider style="margin: 5px 0"></el-divider>
              <div @click="menuClick(1)" class="menu-item">查看电缆段分布</div>
              <div @click="menuClick(2)" class="menu-item">查看详情</div>
            </div>

          </el-popover>

          <div class="info-list grid-content">
            <div class="riskDetail">
              <el-table :data="showData" style="width: 100%"
                        v-if="showData"
                        @row-click="rowClick"
                        @row-contextmenu="rowRClick"
                        @row-dblclick="rowDBClick"
                        max-height="458"
                        :default-sort="{ prop: 'risk_score', order: 'descending' }"
                        row-style="cursor: pointer">
                <el-table-column label="序号" width="80" prop="cable_section_number" sortable>
                  <template #default="scope">
                    <div style="display: flex; align-items: center">
                      <span style="margin-left: 10px">{{ scope.row.cable_section_number }}</span>
                    </div>
                  </template>
                </el-table-column>
                <el-table-column label="线路名称">
                  <!--                <el-table-column label="线路名称" width="130">-->
                  <template #default="scope">
                    <div style="display: flex; align-items: center">
                      <span style="margin-left: 10px">{{ scope.row.line_name }}</span>
                    </div>
                  </template>
                </el-table-column>
                <el-table-column label="起止点">
                  <template #default="scope">
                    <div style="display: flex; align-items: center">
                      <span style="margin-left: 10px">{{ scope.row.start_end }}</span>
                    </div>
                  </template>
                </el-table-column>
                <el-table-column label="风险评分" prop="risk_score" sortable width="105">
                  <template #default="scope">
                    <div style="display: flex; align-items: center">
                      <span style="margin-left: 10px">{{ scope.row.risk_score }}</span>
                    </div>
                  </template>
                </el-table-column>
                <el-table-column label="风险等级" width="80">
                  <template #default="scope">
                    <div style="display: flex; align-items: center">
                      <el-tag :type="getTagTypeByRiskLevel(scope.row.risk_level)">{{ scope.row.risk_level }}</el-tag>
                      <!--                      <span style="margin-left: 10px">{{ scope.row.risk_level }}</span>-->
                    </div>
                  </template>
                </el-table-column>
              </el-table>
            </div>
          </div>

        </div>
      </el-col>
    </el-row>
  </div>
  <el-dialog
      top="3vh"
      draggable
      v-model="dialogRiskDetailVisible"
      :close-on-click-modal="true"
  >
    <RiskSectionDetial v-if="menuTargetItem" :show-data="menuTargetItem"></RiskSectionDetial>
  </el-dialog>
</template>

<style scoped>
.grid-content {
  min-height: 36px;
  background-color: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  width: 100%;
  overflow: hidden;
}

#map-container {
  height: 810px;
}

#chart-container {
  min-width: 300px;
  max-height: 300px;
  margin: auto;
}

.info-list {
  margin-top: 10px;
}

.search-filter-container {
  padding: 15px;
  background-color: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  margin-bottom: 10px;
  user-select: none;
}

.search-filter-area {
  display: flex;
  align-items: center;
  gap: 10px;
}

.riskDetail {
  padding: 20px;
}

.menu-item {
  margin: auto;
}

.menu-header-name {
  font-weight: bold;
  font-size: 15px;
}

.menu-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: rgba(241, 245, 249, 0.6);
  border-radius: 5px;
  transition: all 0.2s ease;
  cursor: pointer;
  padding: 10px;
  margin-bottom: 5px;
  font-weight: 400;
  font-size: 12px;
}

.menu-item:hover {
  background: rgba(226, 232, 240, 0.6);
}
</style>
